package com.xiaotu.spider.tvmao.pageprocessor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Request;

import com.xiaotu.common.exception.SpiderException;
import com.xiaotu.common.exception.SpiderExceptionCode;
import com.xiaotu.common.model.TVPubCommentModel;
import com.xiaotu.common.model.TVRecordModel;
import com.xiaotu.common.model.TVSetsPlotModel;
import com.xiaotu.common.util.Constants;
import com.xiaotu.common.util.HtmlUtil;
import com.xiaotu.common.util.KeywordEncode;
import com.xiaotu.common.util.PageUtils;
import com.xiaotu.common.util.RegexUtils;
import com.xiaotu.common.util.TVProcessUtils;
import com.xiaotu.spider.APageProcessor;

import net.sf.json.JSONObject;

/**
 * @类名 TVmaoPageProcessor
 * @日期 2017年2月15日
 * @作者 高海军
 * @功能 爬取电视猫的过程数据
 */
@Component("TVmaoPageProcessor")
@Scope("prototype")
public class TVmaoPageProcessor extends APageProcessor
{
	
	private static String SEARCH_URL = "http://tvmao.com/servlet/queryobject?type=all&term=";
	
	@Override
	protected Request getStartRequest(JSONObject target)
	{
		return new Request(
				SEARCH_URL + KeywordEncode.encode(target.getString("tvName")));
	}
	
	@Override
	protected String getSpiderType()
	{
		return Constants.SpiderTaskType.TV_TVmao;
	}
	
	@Override
	public String getPageDataType(Page page)
	{
		if (page.getUrl().toString().contains(SEARCH_URL))
			return Constants.PageDataType.SEARCH_LIST;
		else if (page.getUrl().toString().matches("http://tvmao.com/drama/.+="))
			return Constants.PageDataType.TV_RECORD;
		else if (page.getUrl().toString()
				.matches("http://tvmao.com/drama/.+/episode.+"))
			return Constants.PageDataType.TV_PLOTSET;
		return Constants.PageDataType.UNKNOW;
	}
	
	@Override
	public void process(Page page)
	{
		Map<String, Object> tvinfoMap = page.getRequest().getExtras();
		String dataType = this.getPageDataType(page);
		switch (dataType)
		{
			case Constants.PageDataType.SEARCH_LIST:
				this.searchListProcess(page, tvinfoMap);
				break;
			case Constants.PageDataType.TV_RECORD:
				this.tvRecordProcess(page, tvinfoMap);
				break;
			case Constants.PageDataType.TV_PLOTSET:
				this.tvSetsProcess(page, tvinfoMap);
				break;
			default:
				throw new SpiderException(
						SpiderExceptionCode.DataInvalideException);
		}
	}
	
	private void searchListProcess(Page page, Map<String, Object> tvinfoMap)
	{
		List<JSONObject> resultList = page.getJson().toList(JSONObject.class);
		if (resultList == null || resultList.isEmpty())
			throw new SpiderException(
					SpiderExceptionCode.DataInvalideException);
		for (JSONObject jsonObj : resultList)
		{
			List<String> actors;
			
			if (null == jsonObj.get("actors"))
			{
				actors = null;
			}
			else
			{
				actors = Arrays.asList(jsonObj.getString("actors").split(" "));
			}
			
			if (TVProcessUtils.tvMatched(tvinfoMap, jsonObj.getString("name"),
					TVProcessUtils.getTVType(
							this.getTVTypeById(jsonObj.getString("typeId"))),
					actors, null))
			{
				PageUtils.addTargetRequest(page,
						"http://tvmao.com" + jsonObj.getString("url"),
						tvinfoMap);
				return;
			}
		}
		throw new SpiderException(SpiderExceptionCode.DataInvalideException);
		
	}
	
	private void tvRecordProcess(Page page, Map<String, Object> tvinfoMap)
	{
		
		// 评分
		String score = RegexUtils.regexSearch("\\d+(\\.\\d+)?",
				page.getHtml()
						.xpath("//div[@class='white']//span[@class='ml5']/span/text()")
						.all().toString());
		// 评论
		String commCnt = page.getHtml()
				.xpath("//div[@class='section-wrap']/div[@class='mt10']/h2[@class='font20']/a[@class='black_link ml10 font13 normal']/text()")
				.regex("全部\\((" + RegexUtils.REGEX_INTEGER + ")\\)").toString();
		// 添加评论
		List<String> nicknames = page.getHtml()
				.xpath("//div[@class='section-wrap']/div[@class='mt10']/ul[@class='topic_list']/li[@class='clear topic']/div[@class='ml10']/span[@class='user_name']/text()")
				.all();
		List<String> contents = page.getHtml()
				.xpath("//div[@class='section-wrap']/div[@class='mt10']/ul[@class='topic_list']/li[@class='clear topic']/div[@class='ml10']/a[@class='font15']/text()")
				.all();
		List<String> dates = page.getHtml()
				.xpath("//div[@class='section-wrap']/div[@class='mt10']/ul[@class='topic_list']//div[@class='ml10 lt topic_right']//"
						+ "span[@class='rt font12 color999 ' or @class='rt font12 color999 topic_time']/text()")
				.all();
		TVRecordModel model = new TVRecordModel(tvinfoMap.get("tvid") + "",
				tvinfoMap.get("tvName") + "", Constants.SiteName.TVMAO, score,
				null, null, null, commCnt, null,null);
		
		List<TVPubCommentModel> list = new ArrayList<TVPubCommentModel>();
		for (int i = nicknames.size() - 1; i >= 0; i--)
			list.add(new TVPubCommentModel(model.getTvId(), model.getTvName(),
					Constants.SiteName.TVMAO, nicknames.get(i), contents.get(i),
					dates.get(i), null, null));
		// 导演信息
		page.putField(TVPubCommentModel.class.getName(), list);
		page.putField(TVRecordModel.class.getName(), model);
		String tag = page.getHtml()
				.xpath("//div[@class='menu_div']/dl[@class='menu_tab']/dd[3]/a/text()")
				.toString();
		String tagURL = page.getHtml()
				.xpath("//div[@class='menu_div']/dl[@class='menu_tab']/dd[3]/a/@href")
				.toString() + "/0-1";
		if ("分集剧情".equals(tag))
			PageUtils.addTargetRequest(page, tagURL, tvinfoMap);
		
	}
	
	private void tvSetsProcess(Page page, Map<String, Object> tvinfoMap)
	{
		
		String setNo = page.getHtml()
				.xpath("//div[@class='page-content clear']/div[@class='section-wrap']/h2[@class='epi_t']/text()")
				.toString();
		String set = HtmlUtil.delHTMLTag(page.getHtml()
				.xpath("//div[@class='page-content clear']/div[@class='section-wrap']/article[@class='clear epi_c']")
				.toString());
		Pattern p = Pattern.compile("第([0-9]{1,3})集");
		Matcher m = p.matcher(setNo);
		if (m.find())
			page.putField(TVSetsPlotModel.class.getName(),
					new TVSetsPlotModel(tvinfoMap.get("tvid") + "",
							tvinfoMap.get("tvName") + "", m.group(1), set));
		
		List<String> textList = page.getHtml()
				.xpath("//div[@class='page-content']/div[@class='section-wrap']//div[@class='alignct']/div/a/text()")
				.all();
		if (textList != null && !textList.isEmpty())
		{
			List<String> linkList = page.getHtml()
					.xpath("//div[@class='page-content']/div[@class='section-wrap']//div[@class='alignct']/div/a/@href")
					.all();
			for (int i = textList.size() - 1; i > -1; i--)
			{
				if (!textList.get(i).contains("下一集"))
					linkList.remove(i);
			}
			PageUtils.addTargetRequests(page, linkList, tvinfoMap);
		}
	}
	
	private String getTVTypeById(String typeId)
	{
		switch (typeId)
		{
			case "11":
				return "电视剧";
			case "12":
				return "栏目";
			case "51":
				return "电影";
			default:
				return "其他";
		}
	}
	
}
